package com.syf.kit.soa.core;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.syf.core.kit.SyFrameKit;
import com.syf.core.service.context.ServiceContext;
import com.syf.core.service.context.ServiceRequest;
import com.syf.core.service.context.ServiceResponse;
import com.syf.kit.soa.core.send.SyfRpcSender;

import java.util.Map;

@SyFrameKit("书昀平台service跨进程调度器，即soa service client")
public class SyfRemoteServiceInvoker {
    private final SyfRpcSender sender;

    public SyfRemoteServiceInvoker(SyfRpcSender sender) {
        this.sender = sender;
    }

    /**
     * 调用远程的service
     *
     * @param regionName    远程目标region名称，可以理解微服务名
     * @param serviceCode   目标交易码
     * @param reqData       请求数据体
     * @param reqDataClass  请求数据体的类
     * @param respDataClass 响应数据体的类
     * @param currentCtx    当前交易的上下文，方便同步一些链路跟踪类数据
     */
    public <T, R> ServiceResponse<R> callRemoteService(String regionName, String serviceCode, T reqData, Class<T> reqDataClass, Class<R> respDataClass, ServiceContext currentCtx) {
        ServiceRequest request = buildRemoteCallServiceRequest(currentCtx.getRequest());
        request.setDataObj(reqData);
        return sender.callRemoteService(regionName, serviceCode, request, respDataClass);
    }

    /**
     * 调用远程的service
     *
     * @param regionName  远程目标region名称，可以理解微服务名
     * @param serviceCode 目标交易码
     * @param reqDataMap  请求数据map
     * @param currentCtx  当前交易的上下文，方便同步一些链路跟踪类数据
     */
    public ServiceResponse<Map<String, Object>> callRemoteService(String regionName, String serviceCode, Map<String, Object> reqDataMap, ServiceContext currentCtx) {
        ServiceRequest request = buildRemoteCallServiceRequest(currentCtx.getRequest());
        request.setDataObj(reqDataMap);
        String respString = sender.callRemoteService(regionName, serviceCode, request);

        try {
            return sender.getJsonMapper().getObjectMapper().readValue(respString, new TypeReference<ServiceResponse<Map<String, Object>>>() {
            });
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 触发远程的service
     *
     * @param regionName   远程目标region名称，可以理解微服务名
     * @param serviceCode  目标交易码
     * @param reqData      请求数据体
     * @param reqDataClass 请求数据体的类
     * @param currentCtx   当前交易的上下文，方便同步一些链路跟踪类数据
     */
    public <T> void triggerRemoteService(String regionName, String serviceCode, T reqData, Class<T> reqDataClass, ServiceContext currentCtx) {
        ServiceRequest request = buildRemoteCallServiceRequest(currentCtx.getRequest());
        request.setDataObj(reqData);
        sender.triggerRemoteService(regionName, serviceCode, request);
    }

    /**
     * 触发远程的service
     *
     * @param regionName  远程目标region名称，可以理解微服务名
     * @param serviceCode 目标交易码
     * @param reqDataMap  请求数据体map
     * @param currentCtx  当前交易的上下文，方便同步一些链路跟踪类数据
     */
    public void triggerRemoteService(String regionName, String serviceCode, Map<String, Object> reqDataMap, ServiceContext currentCtx) {
        ServiceRequest request = buildRemoteCallServiceRequest(currentCtx.getRequest());
        request.setDataObj(reqDataMap);
        sender.triggerRemoteService(regionName, serviceCode, request);
    }

    /**
     * 关闭
     */
    public void close() {
        sender.close();
    }

    /**
     * 修改调用计数
     */
    private ServiceRequest buildRemoteCallServiceRequest(ServiceRequest sourceRequest) {
        Integer currentCallCount = sourceRequest.getHead().getCallCount();
        sourceRequest.getHead().setCallCount(currentCallCount + 1);

        return sourceRequest.clone();
    }
}
